<template>
  <div class="h-full flex flex-col">
    <div class="flex justify-between">
      <el-button-group class="pb-4">
        <el-button v-if="add?.submitText" type="primary" :icon="EpPlus" @click="addDialog = true">
          {{ add.submitText }}
        </el-button>

        <el-popconfirm v-if="remove" title="确定要删除吗？" @confirm="onRemove(selections)">
          <template #reference>
            <el-button type="danger" :icon="EpDelete">批量删除</el-button>
          </template>
        </el-popconfirm>
      </el-button-group>
    </div>
    <DefaultForm
      v-if="search"
      v-bind="search"
      @submit="onFilter"
      @reset="onFilter"
      :loading="filterLoading"
    />
    <el-skeleton :loading="filterLoading" animated>
      <el-table
        class="flex-1 mb-4"
        :data="data"
        v-bind="table.attrs"
        @selection-change="onSelectionChange"
      >
        <el-table-column type="selection" />
        <template v-for="column of columns" :key="column.id">
          <el-table-column v-if="column?.['slot-default'] === 'picture'" v-bind="column.attrs">
            <template #default="{ row }">
              <div class="flex justify-center items-center">
                <div
                  class="w-12 h-12"
                  v-if="column.attrs?.prop"
                  :style="{ background: `url(${row[column.attrs.prop]}) center / cover` }"
                ></div>
              </div>
            </template>
          </el-table-column>
          <el-table-column v-else-if="column?.['slot-default'] === 'status'" v-bind="column.attrs">
            <template #default="{ row }">
              <el-tag
                v-if="column.attrs?.prop && column.status"
                :type="column.status[row[column.attrs.prop]][1]"
                >{{ column.status[row[column.attrs.prop]][0] }}</el-tag
              >
            </template>
          </el-table-column>
          <el-table-column v-else v-bind="column.attrs" />
        </template>

        <el-table-column fixed="right" label="操作" min-width="120">
          <template #default="{ row }">
            <el-button
              v-if="detail"
              link
              type="success"
              @click="onDetail(row)"
              :disabled="detailLoading"
            >
              {{ detail.form.submitText }}
            </el-button>
            <el-button
              v-if="edit"
              link
              type="primary"
              @click="onEdit(row)"
              :disabled="detailLoading"
            >
              {{ edit.submitText }}
            </el-button>
            <el-popconfirm v-if="remove" title="确定要删除吗？" @confirm="onRemove(row)">
              <template #reference>
                <el-button link type="danger" :disabled="removeLoading">
                  {{ remove.submitText }}
                </el-button>
              </template>
            </el-popconfirm>
            <slot name="operate" :row="row"></slot>
          </template>
        </el-table-column>
      </el-table>
    </el-skeleton>
    <el-pagination
      class="justify-between px-5 mb-4"
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :total="total"
      v-bind="pagination.attrs"
      @change="onPaginationChange"
    />
    <el-dialog
      v-model="detailDialog"
      title="详情"
      :width="lg ? 800 : 1000"
      append-to-body
      destroy-on-close
      :close-on-press-escape="false"
    >
      <el-scrollbar class="p-4" max-height="400px">
        <DefaultDetail v-if="detailInfo && detailDialog" v-bind="detailInfo" />
      </el-scrollbar>
    </el-dialog>
    <el-dialog
      v-model="editDialog"
      title="编辑"
      :width="lg ? 800 : 1000"
      append-to-body
      destroy-on-close
      :close-on-press-escape="false"
    >
      <el-scrollbar class="p-4" max-height="400px">
        <DefaultForm
          v-if="editForm && editDialog"
          v-bind="editForm"
          @submit="onEditSubmit"
          :loading="editLoading"
        />
      </el-scrollbar>
    </el-dialog>
    <el-dialog
      v-model="addDialog"
      title="新增"
      :width="lg ? 800 : 1000"
      append-to-body
      destroy-on-close
      :close-on-press-escape="false"
    >
      <el-scrollbar class="p-4" max-height="400px">
        <DefaultForm v-if="add && addDialog" v-bind="add" @submit="onAdd" :loading="addLoading" />
      </el-scrollbar>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { EpPlus, EpDelete } from '@/assets/icons'
import useHttp from '@/hooks/useHttp'
import http from '@/http'
import { ElMessage } from 'element-plus'
interface Props {
  columns: TableGlobalColumns
  tableKey: string
  table: TableGlobal
  pagination: TableGlobalPagination
  search?: TableGlobalType['search']
  detail?: TableGlobalType['detail']
  add?: TableGlobalType['add']
  edit?: TableGlobalType['edit']
  remove?: TableGlobalType['remove']
  deleteImage?: TableGlobalType['deleteImage']
}
const props = defineProps<Props>()

const data = shallowRef(props.table.data)
const currentPage = ref(props.pagination['current-page'])
const pageSize = ref(props.pagination['page-size'])
const total = ref(props.pagination.total)

const detailInfo = shallowRef<DetailGlobalType | null>(null)
const detailDialog = ref(false)

const editForm = shallowRef<FormGlobalType | null>(null)
const editDialog = ref(false)

const addDialog = ref(false)

const lg = inject<boolean>('<=lg')

const {
  data: filterData,
  request: filterRequest,
  loading: filterLoading
} = useHttp<ApiResponseData>()

let lastQuery: Record<string, any> = {}
const onFilter = async (params: Record<string, any>) => {
  if (!props.search) {
    return
  }
  lastQuery = params
  await filterRequest(props.search.form.action, params, {
    method: props.search.form.method
  })
  if (filterData.value?.status) {
    data.value = filterData.value.data.data
    currentPage.value = filterData.value.data.page
    pageSize.value = filterData.value.data.size
    total.value = filterData.value.data.total
  }
}

const {
  data: detailData,
  request: detailRequest,
  loading: detailLoading
} = useHttp<ApiResponseData>()

const onDetail = async (row: Record<string, any>) => {
  if (!props.detail) {
    return
  }
  const { form, info } = props.detail

  if (!detailInfo.value) {
    detailInfo.value = { ...info }
  }

  const id = row[props.tableKey]

  await detailRequest(
    form.form.action.replace('$1', id),
    {
      id
    },
    {
      method: form.form.method
    }
  )
  if (detailData.value?.status) {
    detailInfo.value = {
      ...detailInfo.value,
      detail: {
        ...detailInfo.value.detail,
        model: detailData.value.data
      }
    }
    detailDialog.value = true
  }
}

const onEdit = async (row: Record<string, any>) => {
  if (!props.edit || !props.detail) {
    return
  }

  if (!editForm.value) {
    editForm.value = { ...props.edit }
  }

  const { form } = props.detail

  const id = row[props.tableKey]

  await detailRequest(
    form.form.action.replace('$1', id),
    {
      id
    },
    {
      method: form.form.method
    }
  )
  if (detailData.value?.status && editForm.value) {
    editForm.value.form.model = detailData.value.data
    editForm.value.fields = structuredClone(props.edit.fields).map((field) => {
      if (field['field-type'] === 'remote-object-select') {
        field.attrs.remote.action = field.attrs.remote.action.replace('$1', id)
      }
      return field
    })
    editDialog.value = true
  }
}

const { data: editData, request: editRequest, loading: editLoading } = useHttp<ApiResponseData>()
const onEditSubmit = async (params: Record<string, any>, removeImages: string[]) => {
  if (!props.edit) {
    return
  }

  await editRequest(props.edit.form.action.replace('$1', params[props.tableKey]), params, {
    method: props.edit.form.method
  })

  if (editData.value?.status) {
    if (props.deleteImage) {
      editLoading.value = true
      await onRemoveImages(removeImages)
      editLoading.value = false
    }

    await onFilter({})
    editDialog.value = false
  }
}

let selections: Array<Record<string, any>> = []
const onSelectionChange = (rows: Array<Record<string, any>>) => {
  selections = rows
}

const {
  data: removeData,
  request: removeRequest,
  loading: removeLoading
} = useHttp<ApiResponseData>()
const onRemove = async (rows: Record<string, any> | Array<Record<string, any>>) => {
  if (!props.remove) {
    return
  }

  const id = Array.isArray(rows)
    ? rows.map((row) => row[props.tableKey]).join(' ')
    : rows[props.tableKey]

  if (!id) {
    ElMessage.error('未选中任何元素')
    return
  }

  await removeRequest(
    props.remove.form.action.replace('$1', encodeURIComponent(id)),
    {
      id
    },
    {
      method: props.remove.form.method
    }
  )
  if (removeData.value?.status) {
    await onFilter({})
  }
}

const { data: addData, request: addRequest, loading: addLoading } = useHttp<ApiResponseData>()
const onAdd = async (params: Record<string, any>, removeImages: string[]) => {
  if (!props.add) {
    return
  }

  await addRequest(props.add.form.action, params, {
    method: props.add.form.method
  })
  if (addData.value?.status) {
    if (props.deleteImage) {
      addLoading.value = true
      await onRemoveImages(removeImages)
      addLoading.value = false
    }
    await onFilter({})
    addDialog.value = false
  }
}

const onPaginationChange = async (currentPage: number, pageSize: number) => {
  onFilter({
    ...lastQuery,
    page: currentPage,
    size: pageSize
  })
}

const onRemoveImages = async (images: string[]) => {
  if (props.deleteImage && images && images.length > 0) {
    const { fieldname, action, method } = props.deleteImage
    try {
      await http.request({
        url: action,
        method,
        data: {
          [fieldname]: images
        }
      })
      return true
    } catch {
      return false
    }
  }
  return false
}

onMounted(() => {
  onFilter({
    page: props.pagination['current-page'],
    size: props.pagination['page-size']
  })
})
</script>

<style scoped lang="scss"></style>
